gtk: Bubble drag events like motion events
authorBenjamin Otte <otte@redhat.com>
Wed, 19 Feb 2020 03:44:41 +0000 (04:44 +0100)
committerBenjamin Otte <otte@redhat.com>
Sat, 22 Feb 2020 06:33:40 +0000 (07:33 +0100)
Emit crossing events - with a new GTK_CROSSING_DROP type - like we do
for motion events. There is no more special casing for them.

Note that the gesture has not been updated yet, so some obscure behavior
may occur.

gtk/gtkeventcontrollerprivate.h
gtk/gtkmain.c
gtk/gtkwidgetprivate.h

index e9e17f14e4aeef36a0fbdeeb31a8ca1384593b11..571d78f96052da15e01e34fdb35b42ec8e902838 100644 (file)
@@ -24,7 +24,8 @@
 
 typedef enum {
   GTK_CROSSING_FOCUS,
-  GTK_CROSSING_POINTER
+  GTK_CROSSING_POINTER,
+  GTK_CROSSING_DROP
 } GtkCrossingType;
 
 typedef enum {
@@ -47,11 +48,12 @@ typedef struct _GtkCrossingData GtkCrossingData;
  * @new_descendent: the direct child of the receiving widget that
  *     is an ancestor of @new_target, or %NULL if @new_target is not
  *     a descendent of the receiving widget
+ * @drop: the #GdkDrop if this is info for a drop operation
  *
  * The struct that is passed to gtk_event_controller_handle_crossing().
  *
  * The @old_target and @new_target fields are set to the old or new
- * focus or hover location.
+ * focus, drop or hover location.
  */
 struct _GtkCrossingData {
   GtkCrossingType type;
@@ -61,6 +63,7 @@ struct _GtkCrossingData {
   GtkWidget *old_descendent;
   GtkWidget *new_target;
   GtkWidget *new_descendent;
+  GdkDrop *drop;
 };
 
 struct _GtkEventController
index 20b232c5f6469e73273f99c47a5b386d156eae06..98bb83dd2247591f924acdc083eea83cac60940f 100644 (file)
@@ -1304,12 +1304,14 @@ translate_event_coordinates (GdkEvent  *event,
   return TRUE;
 }
 
-void
+static void
 gtk_synthesize_crossing_events (GtkRoot         *toplevel,
+                                GtkCrossingType  crossing_type,
                                 GtkWidget       *old_target,
                                 GtkWidget       *new_target,
                                 GdkEvent        *event,
-                                GdkCrossingMode  mode)
+                                GdkCrossingMode  mode,
+                                GdkDrop         *drop)
 {
   GtkCrossingData crossing;
   GtkWidget *ancestor;
@@ -1324,12 +1326,13 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
   else
     ancestor = NULL;
 
-  crossing.type = GTK_CROSSING_POINTER;
+  crossing.type = crossing_type;
   crossing.mode = mode;
   crossing.old_target = old_target;
   crossing.old_descendent = NULL;
   crossing.new_target = new_target;
   crossing.new_descendent = NULL;
+  crossing.drop = drop;
 
   crossing.direction = GTK_CROSSING_OUT;
 
@@ -1360,7 +1363,8 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
       check_crossing_invariants (widget, &crossing);
       translate_event_coordinates (event, &x, &y, widget);
       gtk_widget_handle_crossing (widget, &crossing, x, y);
-      gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT);
+      if (crossing_type == GTK_CROSSING_POINTER)
+        gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT);
       widget = gtk_widget_get_parent (widget);
     }
 
@@ -1399,7 +1403,8 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
 
       translate_event_coordinates (event, &x, &y, widget);
       gtk_widget_handle_crossing (widget, &crossing, x, y);
-      gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
+      if (crossing_type == GTK_CROSSING_POINTER)
+        gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
     }
 
   g_list_free (list);
@@ -1445,8 +1450,12 @@ is_pointing_event (GdkEvent *event)
     case GDK_TOUCH_CANCEL:
     case GDK_TOUCHPAD_PINCH:
     case GDK_TOUCHPAD_SWIPE:
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DROP_START:
       return TRUE;
-      break;
+
     default:
       return FALSE;
     }
@@ -1479,21 +1488,6 @@ is_focus_event (GdkEvent *event)
     }
 }
 
-static gboolean
-is_dnd_event (GdkEvent *event)
-{
-  switch ((guint) gdk_event_get_event_type (event))
-    {
-    case GDK_DRAG_ENTER:
-    case GDK_DRAG_LEAVE:
-    case GDK_DRAG_MOTION:
-    case GDK_DROP_START:
-      return TRUE;
-    default:
-      return FALSE;
-    }
-}
-
 static inline void
 set_widget_active_state (GtkWidget       *target,
                          const gboolean   release)
@@ -1549,14 +1543,22 @@ handle_pointing_event (GdkEvent *event)
     case GDK_TOUCH_CANCEL:
       old_target = update_pointer_focus_state (toplevel, event, NULL);
       if (type == GDK_LEAVE_NOTIFY)
-        gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, NULL,
-                                        event, gdk_crossing_event_get_mode (event));
+        gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, old_target, NULL,
+                                        event, gdk_crossing_event_get_mode (event), NULL);
+      break;
+    case GDK_DRAG_LEAVE:
+      old_target = update_pointer_focus_state (toplevel, event, NULL);
+      gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_DROP, old_target, NULL,
+                                      event, GDK_CROSSING_NORMAL, gdk_drag_event_get_drop (event));
       break;
     case GDK_ENTER_NOTIFY:
       if (gdk_crossing_event_get_mode (event) == GDK_CROSSING_GRAB ||
           gdk_crossing_event_get_mode (event) == GDK_CROSSING_UNGRAB)
         break;
       G_GNUC_FALLTHROUGH;
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_MOTION:
+    case GDK_DROP_START:
     case GDK_TOUCH_BEGIN:
     case GDK_TOUCH_UPDATE:
     case GDK_MOTION_NOTIFY:
@@ -1575,14 +1577,18 @@ handle_pointing_event (GdkEvent *event)
           if (!gtk_window_lookup_pointer_focus_implicit_grab (toplevel, device,
                                                               sequence))
             {
-              gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, target,
-                                              event, GDK_CROSSING_NORMAL);
+              gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, old_target, target,
+                                              event, GDK_CROSSING_NORMAL, NULL);
             }
 
           gtk_window_maybe_update_cursor (toplevel, NULL, device);
         }
-
-      if (type == GDK_TOUCH_BEGIN)
+      else if (type == GDK_DRAG_ENTER || type == GDK_DRAG_MOTION || type == GDK_DROP_START)
+        {
+          gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_DROP, old_target, target,
+                                          event, GDK_CROSSING_NORMAL, gdk_drag_event_get_drop (event));
+        }
+      else if (type == GDK_TOUCH_BEGIN)
         gtk_window_set_pointer_focus_grab (toplevel, device, sequence, target);
 
       /* Let it take the effective pointer focus anyway, as it may change due
@@ -1605,8 +1611,8 @@ handle_pointing_event (GdkEvent *event)
           new_target = gtk_widget_pick (GTK_WIDGET (native), x, y, GTK_PICK_DEFAULT);
           if (new_target == NULL)
             new_target = GTK_WIDGET (toplevel);
-          gtk_synthesize_crossing_events (GTK_ROOT (toplevel), target, new_target,
-                                          event, GDK_CROSSING_UNGRAB);
+          gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, target, new_target,
+                                          event, GDK_CROSSING_UNGRAB, NULL);
           gtk_window_maybe_update_cursor (toplevel, NULL, device);
         }
 
@@ -1640,23 +1646,6 @@ handle_key_event (GdkEvent *event)
   return focus_widget ? focus_widget : event_widget;
 }
 
-static GtkWidget *
-handle_dnd_event (GdkEvent *event)
-{
-  GtkWidget *event_widget;
-  GtkWidget *target;
-  gdouble x, y;
-  GtkWidget *native;
-
-  event_widget = gtk_get_event_widget (event);
-
-  gdk_event_get_position (event, &x, &y);
-  native = GTK_WIDGET (gtk_widget_get_native (event_widget));
-  target = gtk_widget_pick (native, x, y, GTK_PICK_DEFAULT);
-
-  return target;
-}
-
 void
 gtk_main_do_event (GdkEvent *event)
 {
@@ -1715,8 +1704,6 @@ gtk_main_do_event (GdkEvent *event)
           goto cleanup;
         }
     }
-  else if (is_dnd_event (event))
-    target_widget = handle_dnd_event (event);
 
   if (!target_widget)
     goto cleanup;
@@ -1812,14 +1799,15 @@ gtk_main_do_event (GdkEvent *event)
       /* Crossing event propagation happens during picking */
       break;
 
-    case GDK_DRAG_ENTER:
     case GDK_DRAG_MOTION:
     case GDK_DROP_START:
       if (gtk_propagate_event (target_widget, event))
         break;
       G_GNUC_FALLTHROUGH;
 
+    case GDK_DRAG_ENTER:
     case GDK_DRAG_LEAVE:
+      /* Crossing event propagation happens during picking */
       gtk_drag_dest_handle_event (target_widget, event);
       break;
 
index 93ded92b509f7ad33ee641e4227874ce255109ed..b1efa36f392b6232dd2f62735431c56e597daf64 100644 (file)
@@ -259,12 +259,6 @@ GdkSurface *       _gtk_widget_get_device_surface          (GtkWidget *widget,
                                                             GdkDevice *device);
 GList *           _gtk_widget_list_devices                 (GtkWidget *widget);
 
-void              gtk_synthesize_crossing_events           (GtkRoot         *toplevel,
-                                                            GtkWidget       *from,
-                                                            GtkWidget       *to,
-                                                            GdkEvent        *source,
-                                                            GdkCrossingMode  mode);
-
 void              _gtk_widget_synthesize_crossing          (GtkWidget       *from,
                                                             GtkWidget       *to,
                                                             GdkDevice       *device,